# -*- coding: utf-8 -*-
#--------------------------------------------------------------------------
# Copyright (c) 2009 Barry Schwartz
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
# 
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.

#--------------------------------------------------------------------------

'''
import cElementTree as ET

from ocaml import *

#--------------------------------------------------------------------------

def create(pill):
    tag = get_node_tag(pill)
    loc = get_node_location(pill)
    contents = get_node_contents(pill)
    return node_makers[tag](loc, contents)

def create2(loc, pill_type, pill):
    tag = eval('get_' + pill_type + '_tag')(pill)
    contents = eval('get_' + pill_type + '_contents')(pill)
    return eval(pill_type + '_makers')[tag](loc, pill_type, contents)

class attr(object):
    table = []
    def add(self, value):
        (attr.table).append(value)
        return str(len(attr.table) - 1)

def locate((file_name, line, column)):
    return str(line) + ';' + str(column) + ';' + file_name

def append_node_list(parent, children):
    for child in children:
        parent.append(create(child))

#--------------------------------------------------------------------------

def make_node_list(loc, node_list):
    n = ET.Element('nodes', location = locate(loc))
    append_node_list(n, node_list)
    return n

def make_command(loc, cmd):
    return ET.Element('command', location = locate(loc), command = attr().add(cmd))

def make_command_box(loc, cmd):
    p = create2(loc, 'box_cmd', cmd)
    n = ET.Element('command-box', location = locate(loc))
    n.append(p)
    return n

def make_gfx_command(loc, cmd):
    p = create2(loc, 'dim_arg_box_gfx_cmd', cmd)
    n = ET.Element('gfx-command', location = locate(loc))
    n.append(p)
    return n

def make_new_galley(loc, (name, measure)):
    return ET.Element('new-galley', location = locate(loc), name = name,
                      measure = attr().add(measure))

def make_new_layout(loc, (name, w, h)):
    return ET.Element('new-layout', location = locate(loc), name = name,
                      width = attr().add(w), height = attr().add(h))

def make_new_area(loc, (name, x, y, width, height, max_top, max_bottom, contents)):
    n = ET.Element('new-area', location = locate(loc), name = name,
                   x = attr().add(x), y = attr().add(y),
                   width = attr().add(width), height = attr().add(height))
    n.set('max-top', attr().add(max_top))
    n.set('max-bottom', attr().add(max_bottom))
    n.set('contents', attr().add(contents)) # FIX: Expand this into a subtree.
    return n

def make_ship_out(loc, (even_layout, odd_layout, page_count)):
    n = ET.Element('ship-out', location = locate(loc), pages = str(page_count))
    n.set('even-layout', even_layout)
    n.set('odd-layout', odd_layout)
    return n

def make_add_to_galley(loc, (galley, contents)):
    n = ET.Element('add-to-galley', location = locate(loc), galley = galley)
    append_node_list(n, contents)
    return n

def new_put_galley_in_vbox(loc, (align, name)):
    return ET.Element('put-galley-in-v-box', location = locate(loc),
                      align = str(align), name = name)

def make_modify_galley_glue(loc, f):
    return ET.Element('modify-galley-glue', location = locate(loc), function = attr().add(f))

def make_paragraph(loc, contents):
    n = ET.Element('paragraph', location = locate(loc))
    append_node_list(n, contents)
    return n

def make_begin_group(loc, ignored_):
    return ET.Element('begin-group', location = locate(loc))

def make_end_group(loc, ignored_):
    return ET.Element('end-group', location = locate(loc))

def make_glyph(loc, g): # FIX: This should take a glyph name rather
                        # than a glyph index. (Indexes can change when
                        # you edit a font.)
    n = ET.Element('glyph', location = locate(loc))
    n.set('glyph-index', str(g))
    return n

def make_letter(loc, char):
    return ET.Element('letter', location = locate(loc), char = str(char))

def make_word_end(loc, nonbreaking):
    return ET.Element('word-end', location = locate(loc), nonbreaking = str(nonbreaking))

def make_space(loc, ignored_):
    return ET.Element('space', location = locate(loc))

def make_float(loc, (name, contents)):
    n = ET.Element('float', location = locate(loc), name = name)
    append_node_list(n, contents)
    return n

def make_glue(loc, (width, height, implicit, discardable)):
    return ET.Element('glue', location = locate(loc),
                      width = attr().add(width), height = attr().add(height),
                      implicit = str(implicit), discardable = str(discardable))

def make_break(loc, (penalty, hyph, pre_break, post_break, no_break)):
    n = ET.Element('break', location = locate(loc), hyph = str(hyph))
    if hyph != None:
        n.set('hyph', str(hyph))
    if pre_break != []:
        p = ET.SubElement(n, 'pre-break', location = locate(loc))
        append_node_list(p, pre_break)
    if post_break != []:
        p = ET.SubElement(n, 'post-break', location = locate(loc))
        append_node_list(p, post_break)
    if no_break != []:
        p = ET.SubElement(n, 'no-break', location = locate(loc))
        append_node_list(p, no_break)
    return n

def make_rule(loc, (width, height, depth)):
    return ET.Element('rule', location = locate(loc), width = attr().add(width),
                      height = attr().add(height), depth = attr().add(depth))

def make_image(loc, (f, w, h)):
    n = ET.Element('image', location = locate(loc), width = attr().add(w), height = attr().add(h))
    n.set('file', f)
    return n

def make_accent(loc, (a, c)):
    n = ET.Element('accent', location = locate(loc), accent = str(a))
    append_node_list(n, c)
    return n

def make_hbox(loc, (direction, contents)):
    n = ET.Element('h-box', location = locate(loc), direction = direction)
    append_node_list(n, contents)
    return n

def make_hbox_to(loc, (direction, width, contents)):
    n = ET.Element('h-box-to', location = locate(loc),
                   direction = direction, width = attr().add(width))
    append_node_list(n, contents)
    return n

def make_hbox_spread(loc, (direction, amount, contents)):
    n = ET.Element('h-box-spread', location = locate(loc),
                   direction = direction, amount = attr().add(amount))
    append_node_list(n, contents)
    return n

def make_vbox(loc, contents):
    n = ET.Element('v-box', location = locate(loc))
    append_node_list(n, contents)
    return n

def make_vbox_to(loc, (height, contents)):
    n = ET.Element('v-box-to', location = locate(loc), height = attr().add(height))
    append_node_list(n, contents)
    return n

def make_vbox_spread(loc, (amount, contents)):
    n = ET.Element('v-box-spread', location = locate(loc), amount = attr().add(amount))
    append_node_list(n, contents)
    return n

def make_phantom(loc, (h, v, contents)):
    n = ET.Element('phantom', location = locate(loc), horizontal = str(h), vertical = str(v))
    append_node_list(n, contents)
    return n

def make_hleaders(loc, (width, contents)):
    n = ET.Element('h-leaders', location = locate(loc), width = attr().add(width))
    append_node_list(n, contents)
    return n

def make_vinsert(loc, (below, contents)):
    n = ET.Element('v-insert', location = locate(loc), below = str(below))
    append_node_list(n, contents)
    return n

def make_position_box(loc, ignored_):  # FIX: Not fully implemented.
    return ET.Element('position-box', location = locate(loc))

def make_table(loc, contents):
    n = ET.Element('table', location = locate(loc))
    append_node_list(n, contents)
    return n

def make_table_entry(loc, (left, right, top, baseline, bottom, contents)):
    n = ET.Element('table-entry', location = locate(loc), left = str(left), right = str(right),
                   baseline = str(baseline), bottom = str(bottom))
    append_node_list(n, contents)
    return n

def make_math(loc, contents):
    n = ET.Element('math', location = locate(loc))
    append_node_list(n, contents)
    return n

def make_math_code(loc, (code, contents)):
    n = ET.Element('math-code', location = locate(loc))
    n.set('math-code', str(code))
    append_node_list(n, contents)
    return n

def make_math_char(loc, (math_code, f, c)):
    n = ET.Element('math-char', location = locate(loc), f = str(f), c = str(c))
    n.set('math-code', str(math_code))
    return n

def make_subscript(loc, contents):
    n = ET.Element('subscript', location = locate(loc))
    append_node_list(n, contents)
    return n

def make_superscript(loc, contents):
    n = ET.Element('superscript', location = locate(loc))
    append_node_list(n, contents)
    return n

def make_fraction(loc, (numer, denom, l, r, t)):
    n = ET.Element('fraction', location = locate(loc),
                   thickness = attr().add(t))
    p = ET.SubElement(n, 'numerator', location = locate(loc))
    append_node_list(p, numer)
    p = ET.SubElement(n, 'denominator', location = locate(loc))
    append_node_list(p, denom)
    p = ET.SubElement(n, 'left', location = locate(loc))
    p.append(create(l))
    p = ET.SubElement(n, 'right', location = locate(loc))
    p.append(create(r))
    return n

def make_underline(loc, contents):
    n = ET.Element('underline', location = locate(loc))
    append_node_list(n, contents)
    return n

def make_overline(loc, contents):
    n = ET.Element('overline', location = locate(loc))
    append_node_list(n, contents)
    return n

def make_math_accent(loc, (family, char, contents)):
    n = ET.Element('math-accent', location = locate(loc), family = family, char = char)
    append_node_list(n, contents)
    return n

def make_root(loc, (small_family, small_char, large_family, large_char, contents)):
    n = ET.Element('root', location = locate(loc))
    n.set('small-family', str(small_family))
    n.set('small-char', str(small_char))
    n.set('large-family', str(large_family))
    n.set('large-char', str(large_char))
    append_node_list(n, contents)
    return n    

def make_left_right(loc, node_list_list):
    n = ET.Element('left-right', location = locate(loc))
    for nl in node_list_list:
        p = ET.SubElement(n, 'node-list', location = locate(loc))
        append_node_list(p, nl)
    return n

def make_math_style(loc, style):
    n = ET.Element('math-style', location = locate(loc))
    n.set('math-style', style)
    return n

def make_index_position(loc, ip):
    return ET.Element('index-position', location = locate(loc), position = ip)

node_makers = {
    'Nodes' : make_node_list,
    'Command' : make_command,
    'CommandBox' : make_command_box,
    'GfxCommand' : make_gfx_command,
    'NewGalley' : make_new_galley,
    'NewLayout' : make_new_layout,
    'NewArea' : make_new_area,
    'ShipOut' : make_ship_out,
    'AddToGalley' : make_add_to_galley,
    'PutGalleyInVBox' : new_put_galley_in_vbox,
    'ModifyGalleyGlue' : make_modify_galley_glue,
    'Paragraph' : make_paragraph,
    'BeginGroup' : make_begin_group,
    'EndGroup' : make_end_group,
    'Float' : make_float,
    'Glyph' : make_glyph,
    'Letter' : make_letter,
    'WordEnd' : make_word_end,
    'Space' : make_space,
    'Glue' : make_glue,
    'Break' : make_break,
    'Rule' : make_rule,
    'Image' : make_image,
    'Accent' : make_accent,
    'HBox' : make_hbox,
    'HBoxTo' : make_hbox_to,
    'HBoxSpread' : make_hbox_spread,
    'VBox' : make_vbox,
    'VBoxTo' : make_vbox_to,
    'VBoxSpread' : make_vbox_spread,
    'Phantom' : make_phantom,
    'HLeaders' : make_hleaders,
    'VInsert' : make_vinsert,
    'PositionBox' : make_position_box,
    'Table' : make_table,
    'TableEntry' : make_table_entry,
    'Math' : make_math,
    'MathCode' : make_math_code,
    'MathChar' : make_math_char,
    'SubScript' : make_subscript,
    'SuperScript' : make_superscript,
    'Fraction' : make_fraction,
    'Underline' : make_underline,
    'Overline' : make_overline,
    'MathAccent' : make_math_accent,
    'Root' : make_root,
    'LeftRight' : make_left_right,
    'MathStyle' : make_math_style,
    'IndexPosition' : make_index_position,
}

#--------------------------------------------------------------------------

def make_empty_xxxxx(loc, pill_type, x):  # FIX: Not fully implemented.
    return ET.Element('abcdefg', location = locate(loc))

#--------------------------------------------------------------------------

def make_put_box(loc, pill_type, (dx, dy, b)):
    n = ET.Element('put-box', location = locate(loc))
    if isinstance(dx, num) or isinstance(dx, dim):
        n.set('dx', str(dx))
        n.set('dy', str(dy))
    else:
        n.set('dx', attr().add(dx))
        n.set('dy', attr().add(dy))
    n.set('box', attr().add(b))
    return n

def make_set_color(loc, pill_type, color):
    return ET.Element('set-color', location = locate(loc), color = str(color))

def make_set_bg_color(loc, pill_type, color):
    return ET.Element('set-bg-color', location = locate(loc), color = str(color))

def make_set_alpha(loc, pill_type, alpha):
    return ET.Element('set-alpha', location = locate(loc), color = str(alpha))

def make_set_line_width(loc, pill_type, width):
    return ET.Element('set-line-width', location = locate(loc), width = str(width))

def make_set_miter_limit(loc, pill_type, limit):
    return ET.Element('set-miter-limit', location = locate(loc), limit = str(limit))

def make_set_line_cap(loc, pill_type, lc):
    n = ET.Element('set-line-cap', location = locate(loc))
    n.set('line-cap', lc)
    return n

def make_set_line_join(loc, pill_type, lc):
    n = ET.Element('set-line-join', location = locate(loc))
    n.set('line-join', lc)
    return n

gfx_cmd_makers = {
    'PutBox' : make_put_box,
    'SetColour' : make_set_color,
    'SetBgColour' : make_set_bg_color,
    'SetAlpha' : make_set_alpha,
    'SetLineWidth' : make_set_line_width,
    'SetMiterLimit' : make_set_miter_limit,
    'SetLineCap' : make_set_line_cap,
    'SetLineJoin' : make_set_line_join,
    'Draw' : make_empty_xxxxx,
}

#--------------------------------------------------------------------------

def make_gfx_cmd(loc, pill_type, cmd):
    n = ET.Element('gfx-cmd', location = locate(loc))
    p = create2(loc, pill_type, cmd)
    n.append(p)
    return n

def make_par_cmd(loc, pill_type, cmd):
    if cmd[0] == 'VInsert':
        n = ET.Element('v-insert', location = locate(loc), below = str(cmd[1]))
        n.add('box-list', cmd[2])
    elif cmd[0] == 'CallParFunction':
        n = ET.Element('call-par-function', location = locate(loc), function = attr().add(cmd[1]))
    else:
        assert False
    return n

def make_page_cmd(loc, pill_type, cmd):
    if cmd[0] == 'SetNextLayout':
        n = ET.Element('set-next-layout', location = locate(loc), layout = cmd[1])
    elif cmd[0] == 'SetMark':
        n = ET.Element('set-mark', location = locate(loc), mark = cmd[1], contents = cmd[2])
    elif cmd[0] == 'CallPageFunction':
        n = ET.Element('call-page-function', location = locate(loc), function = attr().add(cmd[1]))
    elif cmd[0] == 'Float':
        n = ET.Element('float', location = locate(loc), floating = attr().add(cmd[1]))
    else:
        assert False
    return n

def make_special(loc, pill_type, cmd):
    if cmd[0] == 'DVI_Special':
        n = ET.Element('dvi-special', location = locate(loc), special = cmd[1])
    if cmd[0] == 'PDF_Code':
        n = ET.Element('pdf-code', location = locate(loc), special = cmd[1])
    else:
        assert False
    return n

box_cmd_makers = {
    'GfxCmd' : make_gfx_cmd,
    'ParCmd' : make_par_cmd,
    'PageCmd' : make_page_cmd,
    'Special' : make_special,
}

#--------------------------------------------------------------------------
'''
